#ifndef SINTACTICO_H
#define SINTACTICO_H

#include <iostream>
#include "asignar.h"
#include "variable.h"
#include "retorne.h"
#include "llamar.h"
#include "escriba.h"
#include "lea.h"
#include "lexico.h"
#include "caso.h"
#include "entero.h"
#include "booleano.h"
#include "cadena.h"
#include "caracter.h"
#include "real.h"
#include "procedimiento.h"
#include "funcion.h"
#include "exprbinaria.h"
#include "exprunary.h"
#include "para.h"
#include "mientras.h"
#include "repita.h"
#include "si.h"
#include "indexvariable.h"
#include "variablefuncion.h"
#include "pinvariable.h"
#include "pin.h"
#include "modo.h"
using namespace std;
class Sintactico
{
public:
    Sintactico(string dir);
    Sentencia* S();
    Sentencia* PROGRAMAS();
    void PIN(Tabla_Simbolos* ts);
    void PIN_PRI(Tabla_Simbolos* ts);
    int TIPOSEN();
    void PINES(Tabla_Simbolos* ts,int modo);
    void PINES_PRI(Tabla_Simbolos* ts, int modo);
    void DECLARAR(Tabla_Simbolos* ts);
    void DECLARAR_PRI(Tabla_Simbolos* ts);
    void ENTER();
    void ENTER_PRI();
    Tipo_ts* TIPODATO();
    Tipo_ts* ARREGLO();
    vector<TipoDato*> DIMS(vector<TipoDato*> index);
    vector<TipoDato*> DIMS_PRI(vector<TipoDato*> index);
    TipoDato* DIMS_2PRI();
    vector<string> LISTAID(vector<string> ids);
    vector<string> LISTAID_PRI(vector<string> ids);
    void REGISTRO();
    void REGISTRO_PRI();
    void PROCEDIMIENTO_FUNCION();
    void PROCEDIMIENTO_FUNCION_PRI();
    vector<Expr*> EXPRS(vector<Expr*> expr);
    vector<Expr*> EXPRS_PRI(vector<Expr*> expr);
    Expr* EXPR();
    Expr* R();
    Expr* R_PRI(Expr* E_);
    Expr* E();
    Expr* E_PRI(Expr* T_);
    Expr* T();
    Expr* T_PRI(Expr* P_);
    Expr* P();
    Expr* P_PRI(Expr* F_);
    Expr* F();
    TipoDato* LITERAL();
    vector<TipoDato*> LITERAL_PRI(vector<TipoDato*> tipodato);
    vector<TipoDato*> LITERAL_2PRI(vector<TipoDato*> tipodato);
    Retorne* RETORNE();
    Tipo_ts* TIPORETORNO();
    Sentencia* INTRUCCIONES();
    Sentencia* INSTRUCCION();
    Sentencia* INSTRCICLO();
    Sentencia* INSTRCONDICIONAL();
    void PARAMS(Tabla_Simbolos* ts);
    void PARAMS_PRI(Tabla_Simbolos* ts);
    void PARAMS_2PRI(Tabla_Simbolos* ts);
    Item_ts* PARAM_PRI();
    Item_ts* PARAM();
    Escriba* ESCRIBA();
    Llamar* LLAMAR();
    vector<Expr*> LLAMAR_PRI();
    vector<Expr*> LLAMAR_2PRI();
    Lea* LEA();
    vector<Variable*> LISTAVARIABLES(vector<Variable*> variables);
    vector<Variable*> LISTAVARIABLES_PRI(vector<Variable*> variables);
    Asignar* ASIGNAR();
    Variable* VARIABLE();
    Variable* VARIABLE_PRI();
    Variable* VARIABLE_2PRI();
    Variable* VARIABLE_3PRI();
    Variable* VARIABLE_4PRI();
    vector<Expr *> RANGO(vector<Expr *> rango);
    vector<Expr *> MORERANGO(vector<Expr *> rango);
    Sentencia* SINO();
    CasoList* CASO();
    Sentencia* FINCASO();
    void PROCEDIMIENTO();
    void FUNCION();
    Modo* MODO();
    int TIPOSE();
    Expr* ABV();

    void match(int tokentype);
    void print(Sentencia * sentencia);
    Tabla_Simbolos* getTablaVaribales();
    Tabla_Simbolos* getTablaTipos();
private:
    Lexico *lexico;
    Token *token_actual;
    TokenType tokentype;
    Tabla_Simbolos *tabla_de_tipos;
    Tabla_Simbolos *tabla_de_variables;
    multimap<int,bool> num_de_pines;
    multimap<int,bool>::iterator it;
};

#endif // SINTACTICO_H
